//===============================================================================
// Microsoft Architecture Strategy Team
// LitwareHR - SaaS Sample Application
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================


//===============================================================================
// Microsoft Architecture Strategy Team
// LitwareHR - S+S Sample Application
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

using System;
using System.Data;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;

using Shp.Runtime.Contract;

namespace LitwareHR.PublicApp.WinUX.Entities
{
    public class Position : INotifyPropertyChanged
    {
        private string code;
        private string title;
        private string postedOn;
        private string message;
        private bool isValid;
        private string posType;
        private Guid requestId;

        public bool IsValid
        {
            get { return isValid; }
        }

        private List<EntityField> fields = new List<EntityField>();

        public Position(List<EntityField> fields)
        {
            Initialize(fields);
        }

        public Position(List<EntityField> fields, EntityField[] definition)
        {
            Initialize(fields);
            Validate(definition);
        }

        public Position(DataRow row)
        {
            this.fields = null;

            if (row.Table.Columns.Contains("code"))
                code = row["code"].ToString();

            if (row.Table.Columns.Contains("title"))
                title = row["title"].ToString();

            if (row.Table.Columns.Contains("postedOn"))
            {
                if (row["postedOn"] != DBNull.Value)
                    postedOn = Convert.ToDateTime(row["postedOn"]).ToShortDateString();
            }

        }

        private void Initialize(List<EntityField> fields)
        {
            this.fields = fields;

            foreach (EntityField field in fields)
            {
                if (field.Name.ToUpper().Equals("CODE")) code = field.Value;
                else if (field.Name.ToUpper().Equals("TITLE")) title = field.Value;
                else if (field.Name.ToUpper().Equals("POSTEDON")) postedOn = field.Value;
            }
        }

        private void Validate(EntityField[] definition)
        {
            isValid = true;

            //Check if valid number of columns present
            if (!definition.Length.Equals(fields.Count))
            {
                isValid = false;
                this.message = "Invalid Number of columns!";
            }
            else
            {
                //Check datatype
                foreach (EntityField field in fields)
                {
                    //Check mandatory fields
                    if ((field.Name.Equals("POSTEDON", StringComparison.CurrentCultureIgnoreCase) || 
                        field.Name.Equals("CODE", StringComparison.CurrentCultureIgnoreCase) || 
                        field.Name.Equals("TITLE", StringComparison.CurrentCultureIgnoreCase)) &&
                        field.Value.Trim().Length == 0)
                    {
                        isValid = false;
                        message = field.Name + " can not be blank!";
                        break;
                    }
                    else
                    {
                        //Check data type
                        switch (field.TypeName)
                        {
                            case "Date and time":
                                if (!IsDate((Object)field.Value))
                                    isValid = false;
                                break;
                            case "Short text (up to 255 characters)":
                                if (!IsValidText(field.Value, 255))
                                    isValid = false;
                                break;
                            case "Long text (up to 4000 characters)":
                                if (!IsValidText(field.Value, 4000))
                                    isValid = false;
                                break;
                            case "Number":
                                if (!IsNumeric((Object)field.Value))
                                    isValid = false;
                                break;
                            case "Boolean (Yes | No)":
                                if (!IsBoolean((Object)field.Value))
                                    isValid = false;
                                break;
                            default:
                                isValid = false;
                                break;
                        }
                        if (!isValid)
                        {
                            message = "Invalid field " + field.Name + " Should be " + field.TypeName;
                            break;
                        }
                    }
                }
            }            
        }

        public string Code
        {
            get { return code; }
            set { code = value; NotifyChange("Code"); }
        }

        public string Title
        {
            get { return title; }
            set { title = value; NotifyChange("Title"); }
        }

        public string PostedOn
        {
            get { return postedOn; }
            set { postedOn = value; NotifyChange("postedOn"); }
        }

        public string Message
        {
            get { return message; }
            set { message = value; }
        }

        public string PosType
        {
            get { return posType; }
            set { posType = value; }
        }

        public Guid RequestId
        {
            get { return requestId; }
            set { requestId = value; }
        }


        public List<EntityField> Fields
        {
            get { return fields; }
            set { fields = value; }
        }

        private void NotifyChange(string propName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }

        #region INotifyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion

        #region Validation

        private bool IsDate(Object inValue)
        {
            if (inValue == null)
                return true;

            DateTime dt = new DateTime();
            return DateTime.TryParse(inValue.ToString(), out dt);
        }

        public bool IsBoolean(Object inValue)
        {
            if (inValue == null)
                return true;

            // System should consider YES NO as Boolean (ie., TRUE FALSE)
            string strInValue = inValue.ToString().ToUpper();
            if (strInValue == "YES")
                strInValue = "TRUE";
            else if (strInValue == "NO")
                strInValue = "FALSE";
            
            Boolean val = new Boolean();
            return Boolean.TryParse(strInValue, out val);
        }

        private bool IsNumeric(Object inValue)
        {
            if (inValue == null)
                return true;

            Double val = new Double();
            return Double.TryParse(inValue.ToString(), out val);
        }

        private bool IsValidText(string inValue, int length)
        {
            if (inValue == null)
                return true;

            if (inValue.Length <= length)
                return true;

            return false;
        }

        #endregion

        
    }
}
